<?php
class SiteStructure_Downloader extends Base_Browser
{
  const DEEP_LEVEL = 10;
  /**
   * Current page deep level
   * 
   * @var $level integer
   */
  protected $level = 0;
  /**
   * List url for processing
   * 
   * @var string
   */
  protected $list_url = array ();
  /**
   * List with processed pages array
   * 
   * @var $processed array
   */
  protected $processed = array();
  /**
   * 
   * @var Object
   */
  protected $storage;
  /**
   * 
   * @var String
   */
  protected $encoding;
  
  /**
   * Singleton variable
   * 
   * @var Object
   */
  protected static $self;
  /**
   * Get singleton instance
   */
  public static function instance($parameter= NULL)
  {
    if(!is_object(self::$self))
    {
      self::$self = new SiteStructure_Downloader($parameter); 
    }

    return self::$self;
  }
  /**
   * Class constructor
   * 
   * @param mixed $parameter
   */
  public function __construct($parameter = NULL)
  {
    parent::__construct();
    
    if(is_array($parameter))
    {
      $this->list_url = $parameter;
    }
    elseif(is_string($parameter))
    {
      $this->list_url[] = $parameter;
    }
  }
  /**
   * Method to get current active storage
   */
  protected function getStorage($type = NULL, $config = array())
  {
    if(!is_null($type))
    {
        $this->storage = StorageFactory::instance()->get($type, $config);
    }

    return $this->storage;
  }
  /**
   * Set folder to store downloaded files
   * 
   * @param string $folder_path
   */
  public function folder($folder_path)
  {
    // Check path
    if(!file_exists($folder_path))
    {
      throw new Exception("Folder is not readable.");
    }
    
    $this->getStorage(StorageFactory::FILE, array(
      "path" => $folder_path
    ));
    
    return $this;
  }
  /**
   * Method to set current encoding
   * 
   * @param string $encoding
   */
  public function convert($encoding = NULL)
  {
    if(is_null($encoding))
    {
      throw new Exception("Encoding can not be empty!");
    }
    
    $this->encoding = $encoding;
    
    return $this;
  }  
  /**
   * Method to run actions
   */
  public function execute()
  {
    foreach ($this->list_url as $site_url)
    {
      $this->process($site_url);
    }
  }
  /**
   * Process each site
   * 
   * @param string $url
   */
  protected function process($url, $level = 0)
  {
    // Multiply counter
    $level ++;
    // Append page to processed list
    $this->processed[$url] = $level;
    
    $content = $this->getContent($url);
    
    if(!is_null($content))
    {
      // Get inner links array
      $list_links_inner = $content->getInnerLinks();
      
      // Check for needed deep level
      if(self::DEEP_LEVEL > $level)
      {
        foreach($list_links_inner as $link)
        {
          // Set actual deep level for all new links
          if(! array_key_exists($link, $this->processed))
          {
            $this->processed[$link] = $level + 1;
          }
          // Process each link
          if(array_key_exists($link, $this->processed))
          {
            if(is_numeric($this->processed[$link]))
            {
              if($this->processed[$link] == $level + 1)
              {
                $this->process($link, $level);
                
                $this->processed[$link] = null;
              }
            }
          }
        }
      }
      
      switch ($this->getContentType ())
      {
        case "text":
          
          $this->getStorage()
            ->content($content)
            ->save($this->getEncoding (), $this->encoding);
            
          echo "Level: ", $level, " Link: ", $url, "\n";
          
          break;
      }
    }
  }
}
?> 